package tools

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

// FileReader 实现了读取文件内容的工具
// 该工具允许ReAct智能体读取文本文件的内容
type FileReader struct{}

// Name 返回工具的唯一标识名称
func (fr *FileReader) Name() string {
	return "read_file"
}

// Description 返回工具的功能描述
func (fr *FileReader) Description() string {
	return `读取文本文件的内容并返回。支持多种文本格式，提供安全的文件读取能力。

**参数说明：**
- file_path (string, 必需): 要读取的文件路径
  - 支持相对路径和绝对路径
  - 最大文件大小限制：1MB
  - 最多显示1000行内容
- start_line (int, 可选): 起始行号，从1开始计数，默认为1
- end_line (int, 可选): 结束行号，必须大于等于start_line，默认为100

**使用示例：**
` + "```json" + `
{
  "type": "action",
  "action": "read_file",
  "parameters": {
    "file_path": "test.txt"
  }
}
` + "```" + `

` + "```json" + `
{
  "type": "action",
  "action": "read_file",
  "parameters": {
    "file_path": "config/app.json",
    "start_line": 1,
    "end_line": 50
  }
}
` + "```" + `

` + "```json" + `
{
  "type": "action",
  "action": "read_file",
  "parameters": {
    "file_path": "main.go",
    "start_line": 10,
    "end_line": 30
  }
}
` + "```" + `

**返回结果：**
- 成功: 文件路径、大小、实际读取的行数范围和内容
- 失败: 错误信息（安全检查失败、文件不存在、行号无效等）
- 取消: "文件读取已取消"`
}

// isSafeFilePath 检查文件路径是否安全
func (fr *FileReader) isSafeFilePath(filePath string) error {
	// 清理路径
	cleanPath := filepath.Clean(filePath)

	// 检查文件是否存在
	info, err := os.Stat(cleanPath)
	if err != nil {
		return fmt.Errorf("无法访问文件: %v", err)
	}

	// 检查是否为目录
	if info.IsDir() {
		return fmt.Errorf("路径指向目录而非文件")
	}

	// 检查文件大小（最大1MB）
	if info.Size() > 1024*1024 {
		return fmt.Errorf("文件过大（最大支持1MB），当前大小: %d bytes", info.Size())
	}

	return nil
}

// confirmRead 请求用户确认是否读取文件
func (fr *FileReader) confirmRead(filePath string) bool {
	// 为了测试目的，可以设置环境变量跳过确认
	if os.Getenv("AISH_SKIP_CONFIRM") == "true" {
		return true
	}

	reader := bufio.NewReader(os.Stdin)

	fmt.Printf("\n[FILE] 确认读取文件: %s\n", filePath)
	fmt.Print("请确认是否读取？(y/N): ")

	input, err := reader.ReadString('\n')
	if err != nil {
		return false
	}

	input = strings.TrimSpace(strings.ToLower(input))
	return input == "y" || input == "yes"
}

// Execute 执行文件读取操作
func (fr *FileReader) Execute(args map[string]interface{}) (string, error) {
	// 提取文件路径
	filePath, ok := args["file_path"].(string)
	if !ok {
		return "", fmt.Errorf("file_path 参数是必需的，必须是字符串类型")
	}

	filePath = strings.TrimSpace(filePath)
	if filePath == "" {
		return "", fmt.Errorf("file_path 不能为空")
	}

	// 提取行号参数（可选）
	startLine := 1
	endLine := 100

	if startLineArg, exists := args["start_line"]; exists {
		if val, ok := startLineArg.(float64); ok {
			startLine = int(val)
		} else if val, ok := startLineArg.(int); ok {
			startLine = val
		} else {
			return "", fmt.Errorf("start_line 必须是整数类型")
		}
		if startLine < 1 {
			return "", fmt.Errorf("start_line 必须大于等于1")
		}
	}

	if endLineArg, exists := args["end_line"]; exists {
		if val, ok := endLineArg.(float64); ok {
			endLine = int(val)
		} else if val, ok := endLineArg.(int); ok {
			endLine = val
		} else {
			return "", fmt.Errorf("end_line 必须是整数类型")
		}
		if endLine < startLine {
			return "", fmt.Errorf("end_line 必须大于等于 start_line")
		}
	}

	// 安全检查
	if err := fr.isSafeFilePath(filePath); err != nil {
		return "", fmt.Errorf("安全检查失败: %v", err)
	}

	// 用户确认
	if !fr.confirmRead(filePath) {
		return "文件读取已取消", nil
	}

	// 读取文件内容
	file, err := os.Open(filePath)
	if err != nil {
		return "", fmt.Errorf("无法打开文件: %v", err)
	}
	defer file.Close()

	// 使用bufio.Scanner读取指定行范围
	var content strings.Builder
	scanner := bufio.NewScanner(file)
	currentLine := 1
	readLines := 0
	actualStartLine := startLine
	actualEndLine := 0

	for scanner.Scan() {
		if currentLine >= startLine && currentLine <= endLine {
			content.WriteString(scanner.Text())
			content.WriteString("\n")
			readLines++
			if actualEndLine == 0 {
				actualStartLine = currentLine
			}
			actualEndLine = currentLine
		}
		currentLine++
		if currentLine > endLine {
			break
		}
	}

	if err := scanner.Err(); err != nil {
		return "", fmt.Errorf("读取文件时出错: %v", err)
	}

	// 如果请求的行范围超出文件实际行数，添加提示
	result := content.String()
	if currentLine <= startLine {
		result = "(请求的行范围超出文件实际内容)"
	} else if currentLine <= endLine {
		result += fmt.Sprintf("\n... (文件只有 %d 行，显示到第 %d 行)", currentLine-1, currentLine-1)
	}

	fileInfo, _ := os.Stat(filePath)
	result = fmt.Sprintf("文件: %s\n大小: %d bytes\n总行数: %d\n读取行范围: %d-%d\n内容:\n%s",
		filePath, fileInfo.Size(), currentLine-1, actualStartLine, actualEndLine, result)

	return result, nil
}

// NewFileReader 创建并返回一个新的FileReader实例
func NewFileReader() *FileReader {
	return &FileReader{}
}
